﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Framework.ObjectFactory
{
    /// <summary>
    /// 类型构造者
    /// </summary>
    internal static class ProxyBuilder
    {
        // 用来缓存构造的类型
        private static readonly IDictionary<string, Type> generatedTypes = new Dictionary<string, Type>();
        private static readonly object generateLock = new object();

        /// <summary>
        /// 构造类型
        /// </summary>
        /// <typeparam name="TType"></typeparam>
        /// <typeparam name="TBuilder"></typeparam>
        /// <returns></returns>
        public static Type BuildType<TType, TBuilder>()
            where TType : class
            where TBuilder : ITypeBuilder, new()
        {
            string typeName = GetTypeName<TType>(typeof(TBuilder).Name.Replace("ClassBuilder", ""));

            Type type = TryGetType(typeName);
            if (type != null)
                return type;

            lock (generateLock)
            {
                type = TryGetType(typeName);
                if (type != null)
                    return type;

                TBuilder builder = new TBuilder();
                type = builder.GenerateType(typeName);

                lock (generatedTypes)
                {
                    generatedTypes[typeName] = type;
                }
                return type;
            }
        }

        /// <summary>
        /// 获取类型
        /// </summary>
        /// <param name="className"></param>
        /// <returns></returns>
        private static Type TryGetType(string className)
        {
            lock (generatedTypes)
            {
                Type generatedType;
                if (generatedTypes.TryGetValue(className, out generatedType))
                    return generatedType;
            }
            return null;
        }

        /// <summary>
        /// 获取类型名字
        /// </summary>
        /// <typeparam name="TType"></typeparam>
        /// <param name="classNameSuffix"></param>
        /// <returns></returns>
        private static string GetTypeName<TType>(string classNameSuffix)
        {
            Type iType = typeof(TType);
            if (iType.Name.StartsWith("I") && char.IsUpper(iType.Name, 1))
            {
                return iType.Name.Substring(1) + classNameSuffix;
            }
            else
            {
                return iType.Name + classNameSuffix;
            }
        }
    }
}
